package com.laamella.syntherface.synths.alesis.micron.model;

import com.laamella.syntherface.synths.alesis.micron.model.sysex.PatchSysEx;
import com.laamella.syntherface.synths.alesis.micron.model.sysex.RequestSysEx;
import com.laamella.syntherface.synths.events.SynthWideEvents;
import com.laamella.syntherface.synths.midi.MidiInterface;
import com.laamella.syntherface.synths.models.ParameterModel;
import com.laamella.syntherface.synths.models.StringModel;

/**
 * Main model class for a Micron patch. This class, together with all classes it
 * contains, contains all parameters that a patch contains.
 */
public class Patch {
	public final StringModel name = new StringModel(15);
	public final Voice voice;
	public final Crap crap;
	public final Envelope envelope1;
	public final Envelope envelope2;
	public final Envelope envelope3;
	public final Lfo lfo1;
	public final Lfo lfo2;
	public final Filters filter;
	public final Oscillator oscillator1;
	public final Oscillator oscillator2;
	public final Oscillator oscillator3;
	public final Output output;
	public final PreFilterMix preFilterMixOscillator1;
	public final PreFilterMix preFilterMixOscillator2;
	public final PreFilterMix preFilterMixOscillator3;
	public final PreFilterMix preFilterMixRingModulation;
	public final PreFilterMix preFilterMixNoise;
	public final PreFilterMix preFilterMixExtIn;
	public final SampleAndHold sampleAndHold;
	public final TrackingGenerator tracking;
	public final Effects effects;
	public final ModulationMatrix modulationMatrix;
	public final PostFilterMix postFilterMix;
	public final Arpeggiator arpeggiator;

	private final MidiInterface midiInterface;

	public final PatchSysEx patchSysEx;

	public Patch(final MidiInterface midiInterface) {
		this.midiInterface = midiInterface;
		voice = new Voice(midiInterface);
		oscillator1 = new Oscillator(midiInterface, 1);
		oscillator2 = new Oscillator(midiInterface, 2);
		oscillator3 = new Oscillator(midiInterface, 3);
		crap = new Crap(midiInterface);
		envelope1 = new Envelope(midiInterface, 1);
		envelope2 = new Envelope(midiInterface, 2);
		envelope3 = new Envelope(midiInterface, 3);
		lfo1 = new Lfo(midiInterface, 1);
		lfo2 = new Lfo(midiInterface, 2);
		filter = new Filters(midiInterface);
		output = new Output(midiInterface);
		preFilterMixOscillator1 = new PreFilterMix(midiInterface, PreFilterMix.MixerFor.Oscillator1);
		preFilterMixOscillator2 = new PreFilterMix(midiInterface, PreFilterMix.MixerFor.Oscillator2);
		preFilterMixOscillator3 = new PreFilterMix(midiInterface, PreFilterMix.MixerFor.Oscillator3);
		preFilterMixRingModulation = new PreFilterMix(midiInterface, PreFilterMix.MixerFor.RingModulation);
		preFilterMixNoise = new PreFilterMix(midiInterface, PreFilterMix.MixerFor.Noise);
		preFilterMixExtIn = new PreFilterMix(midiInterface, PreFilterMix.MixerFor.ExtIn);
		sampleAndHold = new SampleAndHold(midiInterface);
		tracking = new TrackingGenerator(midiInterface);
		effects = new Effects(midiInterface);
		modulationMatrix = new ModulationMatrix(midiInterface);
		postFilterMix = new PostFilterMix(midiInterface);
		arpeggiator = new Arpeggiator(midiInterface);
		name.setText("* Empty");

		ParameterModel.dumpDocumentation();

		// this one last, it needs an initialized patch!
		patchSysEx = new PatchSysEx(this);
	}

	/**
	 * TODO figure out how to handle banks, patches, and the whole lot.
	 * 
	 * @throws Exception
	 */
	public void readSettingsFromSysEx() throws Exception {
		midiInterface.updateSynthesizer = false;
		try {
			midiInterface.getResponseToSysEx(new RequestSysEx(1, 1, false), patchSysEx);
			SynthWideEvents.statusUpdate().send("Received patch successfully.");
		} finally {
			midiInterface.updateSynthesizer = true;
		}
	}
}
